package com.efast.cafe.portal;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Primary;
import org.springframework.core.MethodParameter;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.session.data.redis.config.ConfigureRedisAction;
import org.springframework.session.web.http.HttpSessionStrategy;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.servlet.mvc.method.annotation.AbstractMappingJacksonResponseBodyAdvice;

import com.efast.cafe.commponent.log.ext.CafeLogger;
import com.efast.cafe.commponent.log.ext.CafeLoggerFactory;
import com.efast.cafe.framework.app.ApplicationInit;
import com.efast.cafe.framework.bean.ResultBean;
import com.efast.cafe.framework.constant.SecurityConstant;
import com.efast.cafe.framework.exception.GlobalExceptionAdvice;
import com.efast.cafe.framework.feign.constant.FeignConstant;
import com.efast.cafe.framework.filter.CsrfFilter;
import com.efast.cafe.framework.filter.MyAuthenticationFilter;
import com.efast.cafe.framework.jdbc.JdbcDao;
import com.efast.cafe.framework.jdbc.JdbcDaoImpl;
import com.efast.cafe.framework.redis.ObjectRedisTemplate;
import com.efast.cafe.framework.session.MyCookieHttpSessionStrategy;
import com.efast.cafe.framework.spring.SpringContextUtils;
import com.efast.cafe.portal.service.query.listener.TemplateQueryListener;

import redis.clients.jedis.JedisPoolConfig;
//import com.taobao.pandora.boot.PandoraBootstrap;


@SpringBootApplication
@EnableDiscoveryClient //启用服务注册与发现
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
@ComponentScan(basePackages = {"com.efast.cafe.framework","com.efast.cafe.portal","com.efast.cafe.commponent"})
@EnableAsync
@EnableConfigurationProperties
@EnableFeignClients(basePackages={"com.efast.cafe.code"})
public class PortalServiceApplication extends SpringBootServletInitializer{

	CafeLogger logger = CafeLoggerFactory.getLogger(getClass());



	public static void main(String[] args) {
	
		//PandoraBootstrap.run(args);
		SpringApplication.run(PortalServiceApplication.class, args);
		//PandoraBootstrap.markStartupAndWait();
	}

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
		return super.configure(builder);
	}


	@Bean
	public FilterRegistrationBean testFilterRegistration() {
		FilterRegistrationBean registration = new FilterRegistrationBean();
		List<Pattern> patterns = new ArrayList<Pattern>();
		patterns.add(Pattern.compile(SecurityConstant.LOGIN_PATH));
		patterns.add(Pattern.compile(SecurityConstant.LOGOUT_PATH));
		patterns.add(Pattern.compile("/openHTTP/*"));
		patterns.add(Pattern.compile("/favicon.ico"));
		patterns.add(Pattern.compile("/openWS/*"));
		patterns.add(Pattern.compile("/openSocket/*"));
		registration.setFilter(myAuthenticationFilter(patterns));//添加过滤器
		registration.addUrlPatterns("/*");//设置过滤路径，/*所有路径
		registration.setName("myAuthenticationFilter");//设置优先级
		registration.setOrder(1);//设置优先级
		return registration;
	}
	
	@Bean
	public FilterRegistrationBean csrfFilterRegistration() {
		FilterRegistrationBean registration = new FilterRegistrationBean();
		List<Pattern> patterns = new ArrayList<Pattern>();
		patterns.add(Pattern.compile(SecurityConstant.LOGIN_PATH));
		patterns.add(Pattern.compile(SecurityConstant.LOGOUT_PATH));
		patterns.add(Pattern.compile("/openHTTP/*"));
		patterns.add(Pattern.compile("/favicon.ico"));
		patterns.add(Pattern.compile("/openWS/*"));
		patterns.add(Pattern.compile("/openSocket/*"));
		registration.setFilter(myCsrfFilter(patterns));//添加过滤器
		registration.addUrlPatterns("/*");//设置过滤路径，/*所有路径
		registration.setName("myCsrfFilter");//设置优先级
		registration.setOrder(2);//设置优先级
		return registration;
	}


	@Bean(name = "myAuthenticationFilter")
	public MyAuthenticationFilter myAuthenticationFilter(List<Pattern> patterns){
		return new MyAuthenticationFilter(patterns);
	}
	@Bean(name = "myCsrfFilter")
	public CsrfFilter myCsrfFilter(List<Pattern> patterns){
		return new CsrfFilter(patterns);
	}


	@Autowired
	@Qualifier(value = "defaultDataSource")
	private DataSource defaultSource;

	@Bean("jdbcTemplate")
	@Primary
	public JdbcTemplate jdbcTemplate(){
		JdbcTemplate JdbcTemplate = new JdbcTemplate(defaultSource);
		return JdbcTemplate;
	}

	@Bean("jdbcDao")
	@Primary
	public JdbcDao jdbcDao(){
		JdbcDaoImpl jdbcDao = new JdbcDaoImpl();
		jdbcDao.setJdbcTemplate(jdbcTemplate());
		return jdbcDao;
	}


	@Autowired
	private JedisConnectionFactory jedisConnectionFactory;

	@Bean
	@Primary
	public StringRedisTemplate stringRedisTemplate() {
		StringRedisTemplate template = new StringRedisTemplate(jedisConnectionFactory);
		logger.info("StringRedisTemplate bean init success.");
		return template;
	}


	@Bean
	@Primary
	public ObjectRedisTemplate objectRedisTemplate(){
		ObjectRedisTemplate template = new ObjectRedisTemplate(jedisConnectionFactory);
		logger.info("ObjectRedisTemplate bean init success.");
		return template;
	}

	@Bean
	public SpringContextUtils springContextUtils(){
		return new SpringContextUtils();
	}

	@Bean
	public HttpSessionStrategy httpSessionStrategy() {
		HttpSessionStrategy strategy = new MyCookieHttpSessionStrategy();
		return strategy;
	}
	@Bean
	public TemplateQueryListener baseConditionListener(){
		return new TemplateQueryListener();
	}

	@Bean
	public ConfigureRedisAction configureRedisAction() {
		return ConfigureRedisAction.NO_OP;
	}

	/**
	 * 通一异常处理
	 * @ClassName: MyGlobalExceptionAdvice
	 * @Description: TODO(这里用一句话描述这个类的作用)
	 * @author Administrator
	 * @date 2018年8月22日
	 *
	 */
	@ControllerAdvice(annotations = {RestController.class,Controller.class},
			basePackages={"com.efast.cafe.portal.controller","com.efast.cafe.commponent.*.controller"})
	public class MyGlobalExceptionAdvice{
		@ExceptionHandler(value = Exception.class)
		@ResponseBody
		public ResultBean defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
			logger.error("exec error", e);
			return GlobalExceptionAdvice.defaultErrorHandler(req, e);
		}
//		@Override
//		protected void beforeBodyWriteInternal(MappingJacksonValue bodyContainer, MediaType contentType,
//				MethodParameter returnType, ServerHttpRequest request, ServerHttpResponse response) {
//			 if (ResultBean.class.isAssignableFrom(returnType.getParameterType())) {
//		            return;
//		        }
//		        ResultBean resultBean = new ResultBean();
//		        resultBean.setSuccess(true);
//		        resultBean.setObject(bodyContainer.getValue());
//		        bodyContainer.setValue(resultBean);
//			}
	}



}
